#localtime=1
+#-----------------------------------------------------------------------------
+# set the real time clock offset in seconds [default=0 i.e. same as dom0]
+#rtc_timeoffset=3600
+
#-----------------------------------------------------------------------------
# start in full screen
#full-screen=1
int xc_handle;
+long time_offset = 0;
+
shared_iopage_t *shared_page = NULL;
#define BUFFER_IO_MAX_DELAY 100
req->data = tmp1;
}
+void timeoffset_get()
+{
+ char *p;
+
+ p = xenstore_vm_read(domid, "rtc/timeoffset", NULL);
+ if (!p)
+ return;
+
+ if (sscanf(p, "%ld", &time_offset) == 1)
+ fprintf(logfile, "Time offset set %ld\n", time_offset);
+ else
+ time_offset = 0;
+
+ xc_domain_set_time_offset(xc_handle, domid, time_offset);
+
+ free(p);
+}
+
+void cpu_ioreq_timeoffset(CPUState *env, ioreq_t *req)
+{
+ char b[64];
+
+ time_offset += (ulong)req->data;
+
+ sprintf(b, "%ld", time_offset);
+ xenstore_vm_write(domid, "rtc/timeoffset", b);
+}
+
void cpu_ioreq_xchg(CPUState *env, ioreq_t *req)
{
unsigned long tmp1;
case IOREQ_TYPE_XCHG:
cpu_ioreq_xchg(env, req);
break;
+ case IOREQ_TYPE_TIMEOFFSET:
+ cpu_ioreq_timeoffset(env, req);
+ break;
default:
hw_error("Invalid ioreq type 0x%x\n", req->type);
}
}
free(page_array);
#endif
+
+ timeoffset_get();
+
#else /* !CONFIG_DM */
phys_ram_base = qemu_vmalloc(phys_ram_size);
const char *inst,
const char *token);
+int xenstore_vm_write(int domid, char *key, char *val);
+char *xenstore_vm_read(int domid, char *key, int *len);
+
+/* helper2.c */
+extern long time_offset;
+void timeoffset_get(void);
/* xen_platform.c */
void pci_xen_platform_init(PCIBus *bus);
return rc;
}
+
+char *xenstore_vm_read(int domid, char *key, int *len)
+{
+ char *buf = NULL, *path = NULL, *value = NULL;
+
+ if (xsh == NULL)
+ goto out;
+
+ path = xs_get_domain_path(xsh, domid);
+ if (path == NULL) {
+ fprintf(logfile, "xs_get_domain_path(%d): error\n", domid);
+ goto out;
+ }
+
+ pasprintf(&buf, "%s/vm", path);
+ free(path);
+ path = xs_read(xsh, XBT_NULL, buf, NULL);
+ if (path == NULL) {
+ fprintf(logfile, "xs_read(%s): read error\n", buf);
+ goto out;
+ }
+
+ pasprintf(&buf, "%s/%s", path, key);
+ value = xs_read(xsh, XBT_NULL, buf, len);
+ if (value == NULL) {
+ fprintf(logfile, "xs_read(%s): read error\n", buf);
+ goto out;
+ }
+
+ out:
+ free(path);
+ free(buf);
+ return value;
+}
+
+int xenstore_vm_write(int domid, char *key, char *value)
+{
+ char *buf = NULL, *path = NULL;
+ int rc = -1;
+
+ if (xsh == NULL)
+ goto out;
+
+ path = xs_get_domain_path(xsh, domid);
+ if (path == NULL) {
+ fprintf(logfile, "xs_get_domain_path(%d): error\n");
+ goto out;
+ }
+
+ pasprintf(&buf, "%s/vm", path);
+ free(path);
+ path = xs_read(xsh, XBT_NULL, buf, NULL);
+ if (path == NULL) {
+ fprintf(logfile, "xs_read(%s): read error\n", buf);
+ goto out;
+ }
+
+ pasprintf(&buf, "%s/%s", path, key);
+ rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
+ if (rc) {
+ fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
+ goto out;
+ }
+
+ out:
+ free(path);
+ free(buf);
+ return rc;
+}
# Platform configuration keys.
XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'display',
'fda', 'fdb', 'keymap', 'isa', 'localtime',
- 'nographic', 'pae', 'serial', 'sdl',
+ 'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
'vncconsole', 'vncdisplay', 'vnclisten',
'vncpasswd', 'vncunused', 'xauthority']
'on_xend_stop': str,
'on_xend_start': str,
'online_vcpus': int,
+ 'rtc/timeoffset': str,
}
# Values that should be stored in xenstore's /vm/<uuid> that is used
# Check whether values in the configuration have
# changed in Xenstore.
- cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash']
+ cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash',
+ 'rtc/timeoffset']
vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k])
for k in cfg_vm])
self.info.update_with_image_sxp(sxp.from_string(image_sxp))
changed = True
+ # Check if the rtc offset has changes
+ if vm_details.get("rtc/timeoffset", 0) != self.info["platform"].get("rtc_timeoffset", 0):
+ self.info["platform"]["rtc_timeoffset"] = vm_details.get("rtc/timeoffset", 0)
+ changed = True
+
if changed:
# Update the domain section of the store, as this contains some
# parameters derived from the VM configuration.
self.xauthority = vmConfig['platform'].get('xauthority')
self.vncconsole = vmConfig['platform'].get('vncconsole')
+ rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
+
self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
("image/device-model", self.device_model),
("image/display", self.display))
+ self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
self.pid = None
fn=set_value, default=None,
use="CPUS to run the domain on.")
+gopts.var('rtc_timeoffset', val='RTC_TIMEOFFSET',
+ fn=set_value, default="0",
+ use="Set RTC offset.")
+
gopts.var('pae', val='PAE',
fn=set_int, default=1,
use="Disable or enable PAE of HVM domain.")
args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
- 'sdl', 'display', 'xauthority',
+ 'sdl', 'display', 'xauthority', 'rtc_timeoffset',
'acpi', 'apic', 'usb', 'usbdevice', 'keymap' ]
for a in args:
if a in vals.__dict__ and vals.__dict__[a] is not None:
}
}
-int hvm_buffered_io_intercept(ioreq_t *p)
+int hvm_buffered_io_send(ioreq_t *p)
{
struct vcpu *v = current;
spinlock_t *buffered_io_lock;
buffered_iopage_t *buffered_iopage =
(buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va);
unsigned long tmp_write_pointer = 0;
- int i;
-
- /* ignore READ ioreq_t! */
- if ( p->dir == IOREQ_READ )
- return 0;
-
- for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
- if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
- p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
- hvm_buffered_io_ranges[i]->length )
- break;
- }
-
- if ( i == HVM_BUFFERED_IO_RANGE_NR )
- return 0;
buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock;
spin_lock(buffered_io_lock);
return 1;
}
+int hvm_buffered_io_intercept(ioreq_t *p)
+{
+ int i;
+
+ /* ignore READ ioreq_t! */
+ if ( p->dir == IOREQ_READ )
+ return 0;
+
+ for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
+ if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
+ p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
+ hvm_buffered_io_ranges[i]->length )
+ break;
+ }
+
+ if ( i == HVM_BUFFERED_IO_RANGE_NR )
+ return 0;
+
+ return hvm_buffered_io_send(p);
+}
+
int hvm_mmio_intercept(ioreq_t *p)
{
struct vcpu *v = current;
hvm_send_assist_req(v);
}
+void send_timeoffset_req(unsigned long timeoff)
+{
+ ioreq_t p[1];
+
+ if ( timeoff == 0 )
+ return;
+
+ memset(p, 0, sizeof(*p));
+
+ p->type = IOREQ_TYPE_TIMEOFFSET;
+ p->size = 4;
+ p->dir = IOREQ_WRITE;
+ p->data = timeoff;
+
+ p->state = STATE_IOREQ_READY;
+
+ if ( !hvm_buffered_io_send(p) )
+ printk("Unsuccessful timeoffset update\n");
+}
+
static void mmio_operands(int type, unsigned long gpa,
struct hvm_io_op *mmio_op,
unsigned char op_size)
static void rtc_set_time(RTCState *s)
{
struct tm *tm = &s->current_tm;
+ unsigned long before, after; /* XXX s_time_t */
+
+ before = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]);
tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1;
tm->tm_year = from_bcd(s, s->hw.cmos_data[RTC_YEAR]) + 100;
+
+ after = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ send_timeoffset_req(after - before);
}
static void rtc_copy_date(RTCState *s)
* machines were long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
*/
-static inline unsigned long
+unsigned long
mktime (unsigned int year, unsigned int mon,
unsigned int day, unsigned int hour,
unsigned int min, unsigned int sec)
}
extern int hvm_mmio_intercept(ioreq_t *p);
+extern int hvm_buffered_io_send(ioreq_t *p);
extern int hvm_buffered_io_intercept(ioreq_t *p);
static inline int register_portio_handler(
extern void send_pio_req(unsigned long port, unsigned long count, int size,
paddr_t value, int dir, int df, int value_is_ptr);
+void send_timeoffset_req(unsigned long timeoff);
extern void handle_mmio(unsigned long gpa);
extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
extern void hvm_io_assist(struct vcpu *v);
return c;
}
+unsigned long
+mktime (unsigned int year, unsigned int mon,
+ unsigned int day, unsigned int hour,
+ unsigned int min, unsigned int sec);
+
#endif /* __X86_TIME_H__ */
#define IOREQ_TYPE_XOR 4
#define IOREQ_TYPE_XCHG 5
#define IOREQ_TYPE_ADD 6
+#define IOREQ_TYPE_TIMEOFFSET 7
/*
* VMExit dispatcher should cooperate with instruction decoder to